package com.zijidelu.luframework.plugins.tomlock.core.aspect;

import com.zijidelu.luframework.utils.spring.proxy.AspectUtil;
import com.zijidelu.luframework.plugins.tomlock.core.annotation.TomLock;
import com.zijidelu.luframework.plugins.tomlock.core.config.LockProperties;
import com.zijidelu.luframework.plugins.tomlock.core.data.MethodParams;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockHandlerData;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockMethodData;
import com.zijidelu.luframework.plugins.tomlock.core.data.TomLockModeEnum;
import com.zijidelu.luframework.plugins.tomlock.core.exception.TomLockException;
import com.zijidelu.luframework.plugins.tomlock.core.handler.CalcHandlerLockHandler;
import com.zijidelu.luframework.plugins.tomlock.core.handler.CalcMethodLockHandler;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 锁切面。
 *
 * @author ZIJIDELU
 * @datetime 2025/4/9 22:49
 */
@Aspect
@Component
@RequiredArgsConstructor
public class TomLockAspect {
    private final LockProperties lockProperties;
    private final CalcMethodLockHandler calcMethodLockHandler;
    private final CalcHandlerLockHandler calcHandlerLockHandler;

    /**
     * 定义切入点，拦截使用了 TomLock 注解的方法
     */
    @Pointcut("@annotation(com.zijidelu.luframework.plugins.tomlock.core.annotation.TomLock)")
    public void tomLockPointcut() {
    }

    @Around("tomLockPointcut()")
    public Object aroundTomLock(ProceedingJoinPoint joinPoint) {
        final Method method = AspectUtil.getMethod(joinPoint);
        final TomLock tomLock = method.getDeclaredAnnotation(TomLock.class);


        // 计算方法模式
        if (TomLockModeEnum.CALC_METHOD == tomLock.mode()) {
            final TomLockMethodData tomLockMethodData = new TomLockMethodData();
            {
                // 设置分布式锁的前缀
                tomLockMethodData.setLockPrefix(lockProperties.getLockPrefix());
                // 设置分布式锁的描述
                tomLockMethodData.setLockDesc(tomLock.desc().isBlank() ? "TomLock" : tomLock.desc());
                // 设置分布式锁的模式
                tomLockMethodData.setTomLockMode(tomLock.mode());
                // 设置分布式锁的过期时间
                tomLockMethodData.setExpire(tomLock.expire() == -1L ? lockProperties.getExpire() : tomLock.expire());
                // 设置分布式锁的超时时间
                tomLockMethodData.setTimeout(tomLock.timeout() == -1L ? lockProperties.getTimeout() : tomLock.timeout());
                // 设置分布式锁的方法参数列表
                tomLockMethodData.setMethodParamsList(MethodParams.from(method.getParameters(), joinPoint.getArgs()));
                // 设置分布式锁到模块名称
                tomLockMethodData.setModule(tomLock.module());
                // 设置分布式锁到业务名称
                tomLockMethodData.setBusiness(tomLock.business());
                // 设置分布式锁的参数表达式
                tomLockMethodData.setParamExpression(tomLock.paramExpression());
            }
            return calcMethodLockHandler.run(tomLockMethodData, () -> {
                try {
                    return joinPoint.proceed();
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            });
        } else if (TomLockModeEnum.CALC_LOCK_HANDLER == tomLock.mode()) {
            // 计算处理器模式
            final TomLockHandlerData tomLockHandlerData = new TomLockHandlerData();
            {
                // 设置分布式锁的前缀
                tomLockHandlerData.setLockPrefix(lockProperties.getLockPrefix());
                // 设置分布式锁的描述
                tomLockHandlerData.setLockDesc(tomLock.desc().isBlank() ? "TomLock" : tomLock.desc());
                // 设置分布式锁的模式
                tomLockHandlerData.setTomLockMode(tomLock.mode());
                // 设置分布式锁的过期时间
                tomLockHandlerData.setExpire(tomLock.expire() == -1L ? lockProperties.getExpire() : tomLock.expire());
                // 设置分布式锁的超时时间
                tomLockHandlerData.setTimeout(tomLock.timeout() == -1L ? lockProperties.getTimeout() : tomLock.timeout());
                // 设置分布式锁的方法参数列表
                tomLockHandlerData.setMethodParamsList(MethodParams.from(method.getParameters(), joinPoint.getArgs()));
                // 设置分布式锁到处理器类
                tomLockHandlerData.setHandlerClass(tomLock.handler());
                // 设置分布式锁的参数表达式
                tomLockHandlerData.setParamExpression(tomLock.paramExpression());
            }

            return calcHandlerLockHandler.run(tomLockHandlerData, () -> {
                try {
                    return joinPoint.proceed();
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            });
        }

        throw new TomLockException("锁模式暂未实现");
    }
}
